package news.tencent.charco.android.mimc;

import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xiaomi.mimc.MIMCGroupMessage;
import com.xiaomi.mimc.MIMCMessage;
import com.xiaomi.mimc.MIMCMessageHandler;
import com.xiaomi.mimc.MIMCOnlineStatusListener;
import com.xiaomi.mimc.MIMCServerAck;
import com.xiaomi.mimc.MIMCTokenFetcher;
import com.xiaomi.mimc.MIMCUnlimitedGroupHandler;
import com.xiaomi.mimc.MIMCUser;
import com.xiaomi.mimc.common.MIMCConstant;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import news.tencent.charco.android.NewsApplication;
import news.tencent.charco.android.utils.CompressUtils;

public class MimcServer {

    private static final String TAG = "MimcServer";

    private static final String url = "https://mimc.chat.xiaomi.net/api/account/token";
    private static final long appId = 2882303761518119128L;
    private static final String appKey = "5161811990128";
    private static final String appSecurity = "8/kern4emstmHGsxSDpW2Q==";

    private String newsClient = "newsClient";
    private MIMCUser client;

    List<MsgHandleInterface> msgHandleList = new ArrayList<>();

    private static volatile MimcServer instance;

    //private MimcServer() {}

    public static MimcServer getInstance() {
        if (instance == null) {
            synchronized (MimcServer.class) {
                if (instance == null) {
                    try {
                        instance = new MimcServer();
                    } catch (Exception e) {
                        Log.i(TAG,"MimcServer 实例创建失败 : "+ e);
                    }
                }
            }
        }
        return instance;
    }

    public MimcServer(){
        String userId = NewsApplication.getUserId();
        newsClient = userId;

        client = MIMCUser.newInstance(appId, newsClient, NewsApplication.getContext().getExternalFilesDir(null).getAbsolutePath());
        try {
            init(client);
            client.login();
            while (!client.isOnline()) {
                Thread.sleep(200);
            }

            //messenger.createUnlimitedGroup("news", "新闻群");
            String packetId = client.joinUnlimitedGroup(21466739502481408L,"client加入新闻群");
            Log.i(TAG,"client加入新闻群 : "+ packetId);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void finalize() throws java.lang.Throwable {
        super.finalize();
        client.logout();
        Thread.sleep(500);
        Log.i(TAG,"client logout");
        client.destroy();
    }

    private void init(final MIMCUser mimcUser) throws Exception {
        mimcUser.registerTokenFetcher(new MIMCCaseTokenFetcher(appId, appKey, appSecurity, url, mimcUser.getAppAccount()));
        mimcUser.registerOnlineStatusListener(new MIMCOnlineStatusListener() {
            @Override
            public void statusChange(MIMCConstant.OnlineStatus status, String errType, String errReason, String errDescription) {
                Log.i(TAG,"OnlineStatusHandler, Called, "+ mimcUser.getAppAccount() +", isOnline:"+status+", errType:"+ errType+", :"+errReason+", errDesc:"+errDescription);
            }
        });

        // 单聊消息处理
        mimcUser.registerMessageHandler(new MIMCMessageHandler() {
            @Override
            public void handleMessage(List<MIMCMessage> packets) {
                for (MIMCMessage p : packets) {
                    try {
                        String strMsg = CompressUtils.deCompressText(p.getPayload());
                        MsgData msgData = JSON.parseObject(strMsg, MsgData.class);
                        for (MsgHandleInterface msgHandle:msgHandleList){
                            msgHandle.handleMsg(msgData);
                        }
                        Log.i(TAG,"ReceiveMessage, P2P, "+p.getFromAccount()+"-->"+p.getToAccount()
                                        +", packetId:"+p.getPacketId()+", indexTime:"+ msgData.getIndexTime());
                    } catch (Exception e) {
                        Log.i(TAG,"ReceiveMessage, P2P, "+p.getFromAccount()+"-->"+p.getToAccount()
                                        +", packetId:"+p.getPacketId()+", payload:"+new String(p.getPayload()));
                    }
                }
            }

            @Override
            public void handleGroupMessage(List<MIMCGroupMessage> packets) {
            }

            @Override
            public void handleUnlimitedGroupMessage(List<MIMCGroupMessage> list) {
                for (MIMCGroupMessage p : list) {
                    try {
                        MsgData msgData = JSON.parseObject(new String(p.getPayload()), MsgData.class);
                        for (MsgHandleInterface msgHandle:msgHandleList){
                            msgHandle.handleMsg(msgData);
                        }
                        System.out.println(msgData.getHeader());
                    } catch (Exception e) {
                        System.out.println("parseJson error");
                    }
                }
            }

            @Override
            public void handleServerAck(MIMCServerAck serverAck) {
                Log.i(TAG,"ReceiveMessageAck, serverAck:"+ serverAck);
            }

            @Override
            public void handleSendMessageTimeout(MIMCMessage message) {
                Log.i(TAG,"handleSendMessageTimeout, packetId:"+ message.getPacketId());
            }

            @Override
            public void handleSendGroupMessageTimeout(MIMCGroupMessage groupMessage) {
            }

            @Override
            public void handleSendUnlimitedGroupMessageTimeout(MIMCGroupMessage groupMessage) {
            }
        });

        mimcUser.registerUnlimitedGroupHandler(new MIMCUnlimitedGroupHandler(){
            @Override
            public void handleCreateUnlimitedGroup(long var1, String var3, int var4, String var5, Object var6){
                System.out.println(var1);
                System.out.println(var3);
                System.out.println(var4);
                System.out.println(var5);
                System.out.println(var6);
            }

            @Override
            public void handleJoinUnlimitedGroup(long var1, int var3, String var4, Object var5){
                System.out.println(var1);
                System.out.println(var3);
                System.out.println(var4);
                System.out.println(var5);
            }

            @Override
            public void handleQuitUnlimitedGroup(long var1, int var3, String var4, Object var5){
                System.out.println(var1);
                System.out.println(var3);
                System.out.println(var4);
                System.out.println(var5);
            }

            @Override
            public void handleDismissUnlimitedGroup(long var1, int var3, String var4, Object var5){
                System.out.println(var1);
                System.out.println(var3);
                System.out.println(var4);
                System.out.println(var5);
            }

            @Override
            public void handleDismissUnlimitedGroup(long var1){
                System.out.println(var1);
            }
        });
    }

    public void addMsgHandle(MsgHandleInterface handle){
        msgHandleList.add(handle);
    }

    public void sendMessage(String strAccount, Msg msg) throws Exception {
        while (!client.isOnline()) {
            Thread.sleep(200);
        }

        String jsonStr = JSON.toJSONString(msg);
        String packageId = client.sendMessage(strAccount, jsonStr.getBytes(), Constant.TEXT);
        if (packageId == null){
            System.out.println("消息发送失败");
        }
    }

    public void sendUnlimitedGroupMessage(long topicid, Msg msg) throws Exception {
        while (!client.isOnline()) {
            Thread.sleep(200);
        }

        String jsonStr = JSON.toJSONString(msg);
        client.sendUnlimitedGroupMessage(topicid, jsonStr.getBytes(), Constant.TEXT);
    }

    public static class MIMCCaseTokenFetcher implements MIMCTokenFetcher {
        private String httpUrl;
        private long appId;
        private String appKey;
        private String appSecret;
        private String appAccount;

        public MIMCCaseTokenFetcher(long appId, String appKey, String appSecret, String httpUrl, String appAccount) {
            this.httpUrl = httpUrl;
            this.appId = appId;
            this.appKey = appKey;
            this.appSecret = appSecret;
            this.appAccount = appAccount;
        }

        /**
         * @important: 此例中，fetchToken()直接上传(appId/appKey/appSecurity/appAccount)给小米TokenService，获取Token使用
         * 实际上，在生产环境中，fetchToken()应该只上传appAccount+password/cookies给AppProxyService，AppProxyService
         * 验证鉴权通过后，再上传(appId/appKey/appSecurity/appAccount)给小米TokenService，获取Token后返回给fetchToken()
         * @important: appKey/appSecurity绝对不能如此用例一般存放于APP本地
         **/
        @Override
        public String fetchToken() throws Exception {
            URL url = new URL(httpUrl);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("POST");
            con.setDoInput(true);
            con.setDoOutput(true);
            con.addRequestProperty("Content-Type", "application/json");

            JSONObject obj = new JSONObject();
            obj.put("appId", appId);
            obj.put("appKey", appKey);
            obj.put("appSecret", appSecret);
            obj.put("appAccount", appAccount);

            con.getOutputStream().write(obj.toString().getBytes("utf-8"));
            if (200 != con.getResponseCode()) {
                Log.e(TAG,"con.getResponseCode()!=200");
                System.exit(0);
            }

            String inputLine;
            StringBuffer content = new StringBuffer();
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));

            while ((inputLine = in.readLine()) != null) {
                content.append(trim(inputLine));
            }
            in.close();
            Log.i(TAG,content.toString());

            return content.toString();
        }

        public String trim(String str) {
            return str == null ? null : str.trim();
        }
    }
}
